package be.tihh.mgmt.gui;

import be.tihh.mgmt.gui.icontreenode.IconNode;
import be.tihh.mgmt.gui.tree.GuiTreeBuilder;
import be.tihh.mgmt.gui.util.IconFactory;
import be.tihh.mgmt.gui.xml.app.Application;
import be.tihh.mgmt.gui.xml.app.RunCommand;
import be.tihh.mgmt.gui.xml.computers.Computer;
import be.tihh.mgmt.tasks.*;
import be.tihh.mgmt.util.ComputerUtil;
import com.sun.org.apache.xpath.internal.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainScreen {
    private JButton testButton;
    private JTree computersTree;
    private JPanel mainPanel;
    private ComputerDetail computerDetail;
    private JButton wakeUpButton;
    private JButton runButton;
    private JTextField runTextField;
    private JList appList;
    private JButton rebootButton;
    private JButton shutDownButton;
    private appDetail appDetail;
    private ExecutorService tasksExecutorService;
    private ExecutorService guiExecutorService;

    Document computersXml;


    public MainScreen() {
        init();
    }

    private void init() {
        loadComputersXml();
        loadAppsXml();

        testButton.addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                queueActionsForSelectedComputers(new TestTask());
            }
        });
        runButton.addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                queueActionsForSelectedComputers(new RemoteRunner(new RunCommand(runTextField.getText())));
            }
        });
        wakeUpButton.addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                queueActionsForSelectedComputers(new WakeOnLan("192.168.3.255"));
            }
        });

        rebootButton.addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                queueActionsForSelectedComputers(new RemoteRunner(new RunCommand("shutdown -r -f -t 00")));
            }
        });

        shutDownButton.addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                queueActionsForSelectedComputers(new RemoteRunner(new RunCommand("shutdown -s -f -t 00")));
            }
        });

        appDetail.getInstallButton().addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                //todo : check for nulls
                String installerPath = appDetail.getInstallerPathTextField().getText();
                queueActionsForSelectedComputers(new RemoteRunner(new RunCommand(appDetail.getInstallStringTextField().getText().replace("%installerpath%", installerPath))));
            }
        });

        appDetail.getUnInstallButton().addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                //todo : check for nulls
                String unInstallString = appDetail.getUnInstallStringTextField().getText();
                queueActionsForSelectedComputers(new RemoteRunner(new RunCommand(unInstallString)));
            }
        });

        computerDetail.getGetExtraInfoButton().addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                String ipAddress = ComputerUtil.getIpAddress(computerDetail.getComputer());
                computerDetail.getIpAddressTextField().setText(ipAddress);
            }
        });

        tasksExecutorService = Executors.newCachedThreadPool();
        computerDetail.getProcessTasksButton().addActionListener(new ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                tasksExecutorService.submit(new TaskListProcessor(computerDetail.getComputer()));
            }
        });

        //start refreshing task processing status every .5 second
        guiExecutorService = Executors.newCachedThreadPool();
        guiExecutorService.submit(new ComputerDetailRefresher(computerDetail));

    }

    private void loadAppsXml() {

        DefaultListModel listModel = (DefaultListModel) appList.getModel();

        String currentDir = System.getProperty("user.dir");
        String targetRoot = currentDir + "\\res\\apps";
        File f = new File(targetRoot);
        File[] files = f.listFiles();
        for (File file : files) {
            Application app = new Application();

            //load XML
            try {
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                Document applicationXML = db.parse(file);
                String xpath = "/application";
                Node selectedNode = XPathAPI.selectSingleNode(applicationXML, xpath);
                NodeList computerNodes = selectedNode.getChildNodes();
                for (int j = 0; j < computerNodes.getLength(); j++) {
                    Node node = computerNodes.item(j);
                    //todo : check for null
                    if ("name".equals(node.getNodeName())) app.setName(node.getFirstChild().getNodeValue());
                    if ("version".equals(node.getNodeName())) app.setVersion(node.getFirstChild().getNodeValue());
                    if ("install".equals(node.getNodeName())) {
                        NodeList installNodes = node.getChildNodes();
                        String installString = null;
                        String psExecParametersString = null;
                        for (int i = 0; i < installNodes.getLength(); i++) {
                            Node installNode = installNodes.item(i);
                            if ("installstring".equals(installNode.getNodeName())) {
                                installString = installNode.getFirstChild() != null ? installNode.getFirstChild().getNodeValue() : null;
//                                System.out.println("name = " + app.getName());
//                                System.out.println("installString = " + installString);
                            }
                            if ("psexecparameters".equals(installNode.getNodeName())) {
                                psExecParametersString = installNode.getFirstChild() != null ? installNode.getFirstChild().getNodeValue() : null;
//                                System.out.println("psExecParametersString = " + psExecParametersString);
                            }
                        }
                        RunCommand installCommand = new RunCommand(installString, psExecParametersString);
                        app.setInstallCommand(installCommand);
                    }

                    if ("uninstallstring".equals(node.getNodeName()))
                        app.setUnInstallString(node.getFirstChild().getNodeValue());
                    if ("installerpath".equals(node.getNodeName()))
                        app.setInstallerPath(node.getFirstChild().getNodeValue());
                }

                listModel.addElement(app);

            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TransformerException e) {
                e.printStackTrace();
            }

            appList.addListSelectionListener(
                    new ListSelectionListener() {

                        public void valueChanged(ListSelectionEvent e) {
//                        appList.getComponent(e.getFirstIndex());
                            Application app = (Application) appList.getSelectedValue();
//                        JList selectedList = (JList) e.getSource();
//                        Component component = selectedList.getComponent(e.getFirstIndex());
//                        Application app = (Application) new Application();
                            appDetail.getNameTextField().setText(app.getName());
                            appDetail.getVersionTextField().setText(app.getVersion());
                            appDetail.getInstallStringTextField().setText(app.getInstallCommand().getRunString());
                            appDetail.getUnInstallStringTextField().setText(app.getUnInstallString());
                            appDetail.getInstallerPathTextField().setText(app.getInstallerPath());
                        }

                    }
            );

        }

    }

    private void queueActionsForSelectedComputers(ComputerTask computerTask) {
        TreePath[] selectionPaths = computersTree.getSelectionPaths();
        if (selectionPaths != null) {
            for (TreePath selectionPath : selectionPaths) {
                Object userObject = ((DefaultMutableTreeNode) selectionPath.getLastPathComponent()).getUserObject();
                if (Computer.class.equals(userObject.getClass())) {
                    Computer computer = (Computer) userObject;
                    computerTask.initialize(computer);
                    computer.getTasks().add(computerTask);
                    //refresh tasks list
//                    refreshTasksList(computerTask.getComputer());
                }
            }
        }
    }

    private void loadComputersXml() {

        //load XML
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            String currentDir = System.getProperty("user.dir");
            String targetRoot = currentDir + "\\res";
            File remoteFolders = new File(targetRoot + "\\computers.xml");
            computersXml = db.parse(remoteFolders);
            String xpath = "/computers";
            Node selectedNode = XPathAPI.selectSingleNode(computersXml, xpath);

            computersTree = new GuiTreeBuilder().buildTree(selectedNode, this);
//            computersTree = new GuiTreeBuilder().buildTree(selectedNode, computersTree, computerDetail);
//            setGuiTree(selectedNode, computersTree);

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }


    }

    public JTree getTree() {
        return computersTree;
    }

    public ComputerDetail getComputerDetail() {
        return computerDetail;
    }

    public static void main(String[] args) {
/*
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
*/
        JFrame frame = new JFrame("MGMT - Open Management Tool");
        frame.setContentPane(new MainScreen().mainPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    }

    public void refreshComputerDetail(Computer computer) {
        computerDetail.setComputer(computer);
        computerDetail.getNameTextField().setText(computer.getName());
        computerDetail.getIdTextField().setText(computer.getId());
        computerDetail.getMacAddressTextField().setText(computer.getMacAddress());
        computerDetail.getIpAddressTextField().setText(null);

    }

    private void createUIComponents() {
        computersTree = new JTree(new IconNode(0));
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }

}
